/*
复制map6-map-animate.vue ，marker的聚合
*/

<template>
    <div class="container">
        <div class="map-toolbar">
            <el-checkbox-group v-model="checkList" @change="handleCheckChange">
                <el-checkbox :label="item.label" v-bind:key="item.value" :value="item.value"
                             v-for="item in chooseData"></el-checkbox>
            </el-checkbox-group>
        </div>
        <div
                id="map"
                class="map-container"
        />
    </div>
</template>
<script>
import 'maptalks/dist/maptalks.css'
import * as maptalks from 'maptalks'
import {ClusterLayer} from 'maptalks.markercluster'

const logo = require('../assets/logo.png')

// const geoJson = constant.getXiamen()
const geoJson = require('@/static/xiamen.json')

const schoolCoordinate = [
  {
    adcode: 510104,
    name: '小学校',
    center: [118.13734735854666, 24.498801064931087],
    parent: {
      adcode: 510100
    }
  }, {
    adcode: 510104,
    name: '大学校',
    center: [118.11804966596969, 24.47633923130772],
    parent: {
      adcode: 510100
    }
  }
]

const hospitalCoordinate = [
  {
    adcode: 510104,
    name: '小医院',
    center: [118.18303419164465, 24.51143878000599],
    parent: {
      adcode: 510100
    }
  }, {
    adcode: 510104,
    name: '大医院',
    center: [118.19412188942488, 24.53586932160701],
    parent: {
      adcode: 510100
    }
  }

]

export default {
  name: 'MapCustom',
  data () {
    return {
      // 地图引擎
      mapEngine: null,
      map: this,
      center: [118.13245430046891, 24.495713873147764],
      urlTemplate: 'https://{s}.basemaps.cartocdn.com/light_all/{z}/{x}/{y}.png',
      subdomains: ['a', 'b', 'c', 'd'],
      attribution: null,
      // 倾斜度
      pitch: 50,
      // toolbar
      // 旋转
      whirl: null,
      // 放大/缩小
      zoom: 12,
      // 轴承
      bearing: 0,
      // 屏幕坐标
      containerPoint: {x: null, y: null},
      // 地图坐标
      coordinatePoint: {x: null, y: null},
      geoJson: geoJson,
      // 类型复选框
      checkList: [],
      chooseData: [{
        label: '学校',
        value: 'school'
      }, {
        label: '医院',
        value: 'hospital'
      }],
      // 保持选择的图层的名称
      checkLayers: [],
      // 是否禁用测距工具
      distanceTool: null,
      // 绘制工具
      drawTool: null,
      // 测面工具
      areaTool: null
    }
  },
  mounted () {
    const _t = this
    this.$nextTick(() => {
      _t.mapEngine = _t.initMap()

      // 创建图层
      new maptalks.VectorLayer('v').addTo(_t.mapEngine)

      // 锁定视角
      _t.lockView()

      // 创建工具栏
      _t.addToolbar()

      // 增加缩放工具
      _t.addZoomTool()

      // 画区域面
      _t.drawArea()

      // 增加测距工具
      _t.distanceTool = _t.addDistanceTool()

      // 绘制
      // 创建图层
      new maptalks.VectorLayer('drawLayer').addTo(_t.mapEngine)
      const drawLayer = _t.mapEngine.getLayer('drawLayer')
      _t.addDrawTool(drawLayer)
      _t.addDrawToolbar(drawLayer)

      // 测面工具
      _t.addAreaTool()

      _t.mapAnimate()
      _t.addAnimateToolbar()

      // 创建学校和医院的mark图层
      // new maptalks.VectorLayer('schoolMark').addTo(_t.mapEngine)
      // new maptalks.VectorLayer('hospitalMark').addTo(_t.mapEngine)
      const symbol = {
        // 聚合最大半径
        maxClusterRadius: 160,
        // 聚合的最大缩放比例，也就是当缩放到某一个层级时，进行聚合
        maxClusterZoom: 19,
        // 是否开启动画，默认true（开启）
        animation: true,
        // 动画时长
        animationDuration: 30,
        // textSumProperty: '',
        // 这里的属性，可以看官网，都是统一的
        // symbol: {},
        textSymbol: {
          // 文本呈现的样式，默认是: monospace, 当你设置 textFont时会覆盖这个属性
          textFaceName: 'monospace',
          // 字体大小
          textSize: 16
        }
      }
      new ClusterLayer('schoolMark', symbol).addTo(this.mapEngine)
      new ClusterLayer('hospitalMark', symbol).addTo(this.mapEngine)

      // 增加事件，监听获取到鼠标点击的坐标
      _t.mapEngine.on('click', function (e) {
        _t.containerPoint = e.containerPoint
        _t.coordinatePoint = _t.mapEngine.containerPointToCoordinate(e.containerPoint)
        console.log('屏幕坐标：' + JSON.stringify(_t.containerPoint))
        console.log('地图坐标：' + JSON.stringify(_t.coordinatePoint))
      })
    })
  },

  methods: {

    /**
       * 初始化地图
       */
    initMap () {
      const _t = this
      return new maptalks.Map('map', {
        // 默认中心点点位
        center: _t.center,
        // 缩放层级
        zoom: _t.zoom,
        // 倾斜度
        pitch: _t.pitch,
        // 最小缩放层级
        minZoom: 1,
        // 最大缩放层级
        maxZoom: 18,
        baseLayer: new maptalks.TileLayer('base', {
          // 电子地图图层
          urlTemplate: _t.urlTemplate,
          subdomains: _t.subdomains,
          attribution: _t.attribution
        })
      })
    },

    /**
       * 限制地图区域
       */
    lockView () {
      const extent = this.mapEngine.getExtent()
      this.mapEngine.setMaxExtent(extent)
    },

    /**
       * 添加图层
       */
    addLayer () {
      return new maptalks.VectorLayer('v').addTo(this.mapEngine)
    },

    /**
       * 创建工具栏
       */
    addToolbar () {
      const _t = this
      const map = this.mapEngine
      new maptalks.control.Toolbar({
        items: [
          {
            item: '测距',
            click: () => {
              if (_t.distanceTool.isEnabled()) {
                _t.distanceTool.disable()
              } else {
                _t.distanceTool.enable()
              }
            }
          },
          {
            item: '放大',
            click: () => {
              map.setZoom(_t.zoom += 1)
            }
          },
          {
            item: '缩小',
            click: () => {
              map.setZoom(_t.zoom -= 1)
            }
          },
          {
            item: '旋转',
            click: () => {
              map.setBearing(_t.bearing -= 50)
            }
          },
          {
            item: '重置',
            click: () => {
              _t.mapDataReset(map)
            }
          },
          {
            item: '锁定',
            click: (t) => {
              if (t.target.item === '锁定') {
                map.setOptions({
                  // 可拖动
                  draggable: false,
                  // 平移
                  dragPan: false,
                  // 旋转
                  dragRotate: false,
                  // 间距
                  dragPitch: false,
                  // 滚动缩放
                  scrollWheelZoom: false,
                  // 点击 缩放
                  touchZoom: false,
                  // 双击缩放
                  doubleClickZoom: false
                })
                t.target.item = '取消锁定'
              } else {
                map.setOptions({
                  // 可拖动
                  draggable: true,
                  // 平移
                  dragPan: true,
                  // 旋转
                  dragRotate: true,
                  // 间距
                  dragPitch: true,
                  // 滚动缩放
                  scrollWheelZoom: true,
                  // 点击 缩放
                  touchZoom: true,
                  // 双击缩放
                  doubleClickZoom: true
                })
                t.target.item = '锁定'
              }
            }
          }
        ]
      }).addTo(map)
    },

    /**
       * 增加缩放工具
       */
    addZoomTool () {
      new maptalks.control.Zoom({
        // 工具位置
        position: 'top-left',
        // 是否是以线段条方式展示
        slider: false,
        // 是否显示缩放级别文本框
        zoomLevel: true
      }).addTo(this.mapEngine)
    },

    /**
       * 地图数据重置
       */
    mapDataReset () {
      this.pitch = 50
      this.bearing = 0
      this.zoom = 14
      this.mapEngine.setPitch(this.pitch)
      this.mapEngine.setBearing(this.bearing)
      this.mapEngine.setZoom(this.zoom)
    },

    /**
       * 再图层上画面
       */
    drawArea () {
      const _t = this
      const layer = _t.mapEngine.getLayer('v')
      _t.drawAreaPolygon(_t.geoJson, layer)
      layer.setOptions({
        // 启用高度绘制
        enableAltitude: true,
        altitudeProperty: 'altitude',
        // 绘制高度线
        drawAltitude: {
          lineWidth: 1,
          lineColor: '#000'
        }
      })
    },

    /**
       * 根据geojson画区域面
       * @param geoJson geoJson数据
       * @param layer 需要话的图层
       */
    drawAreaPolygon (geoJson, layer) {
      const geometry = maptalks.GeoJSON.toGeometry(geoJson)

      const centerCoordinates = []
      if (geometry) {
        geometry.forEach(g => {
          g.setSymbol({
            // 线色
            lineColor: '#34495e',
            // 线宽
            lineWidth: 1,
            // 填充色
            polygonFill: 'rgb(135,196,240)',
            // 不透明度
            polygonOpacity: 0.2
          })
          // 设置信息框
          g.setInfoWindow({
            title: g.properties.name,
            content: '<br style="color:#f00">中心点：' + g.properties.center + ' </br>行政区划：' + g.properties.adcode + ' </br>父级行政区划：' + g.properties.parent.adcode + '</div>'
          })
          g.setMenu({
            width: 160,
            custom: false,
            items: [
              {
                item: '菜单一',
                click: function () {
                  alert('Query Clicked!')
                  return false
                }
              },
              '-',
              {item: '菜单二', click: function () { alert('Edit Clicked!') }},
              {item: '菜单三', click: function () { alert('About Clicked!') }}
            ]
          })
          // 鼠标交互事件监听
          g.on('mouseenter', function (e) {
            e.target.updateSymbol({
              polygonFill: '#f00'
            })
          }).on('mouseout', function (e) {
            e.target.updateSymbol({
              polygonFill: 'rgb(135,196,240)'
            })
          }).on('click', function (e) {
            e.target.openInfoWindow(e.coordinate)
          })

          // 获取中心坐标
          centerCoordinates.push(g.properties)
        })
      }
      layer.addGeometry(geometry)

      // this.drawMark(centerCoordinates, layer)
    },

    drawMark (centerPointList, layer) {
      if (!centerPointList) {
        console.log('无区域中心点数据')
        return
      }
      const info = {content: '', width: 150, minHeight: 100}
      const result = []
      // 这里 d 的数据格式是数组，如：[-0.113049, 51.498568]
      centerPointList.forEach(d => {
        if (!d.info) {
          d.info = info
        }
        // 设有高度、高亮的mark
        const mark = new maptalks.Marker(d.center, {
          symbol: {
            markerType: 'square',
            markerFile: logo,
            markerWidth: 10,
            markerHeight: 0,
            markerDx: 0,
            markerDy: 0,
            markerOpacity: 1
          },
          properties: {
            // 高度设置
            altitude: 0
          }
        })
        mark.setInfoWindow({
          title: d.name,
          content: '<div>' + d.adcode + '</div>',
          // autoPan: true,
          width: d.info.width,
          minHeight: d.info.minHeight
        })

        mark.animate({
          symbol: {
            markerWidth: 40,
            markerHeight: 40
          },
          properties: {
            altitude: 800
          }
        }, {
          duration: 150
        }, function (frame) {
          if (frame.state.playState === 'finished') {
            console.log('animation finished')
          }
        })

        mark.setZIndex(1000)
        result.push(mark)
      })
      layer.addMarker(result)
      return result
    },

    // 复选框选中
    handleCheckChange (data) {
      console.log(data)
      const _t = this
      // 清除图层
      this.checkLayers.forEach(l => {
        _t.mapEngine.getLayer(l).clear()
      })

      const schoolMarkLayer = this.mapEngine.getLayer('schoolMark')
      const hospitalMarkLayer = this.mapEngine.getLayer('hospitalMark')
      data.forEach(d => {
        if (d === '学校') {
          _t.drawMark(schoolCoordinate, schoolMarkLayer)
          _t.checkLayers.push('schoolMark')
        }
        if (d === '医院') {
          _t.drawMark(hospitalCoordinate, hospitalMarkLayer)
          _t.checkLayers.push('hospitalMark')
        }
      })
    },

    /**
       * 测距工具
       * @returns {*}
       */
    addDistanceTool () {
      return new maptalks.DistanceTool({
        symbol: {
          lineColor: '#34495e',
          lineWidth: 2
        },
        // 请看 symbol属性说明文档：https://github.com/maptalks/maptalks.js/wiki/Symbol-Reference
        // 绘制的线的样式
        vertexSymbol: {
          // 绘制的marker类型，也就是简单形状，支持：ellipse cross x diamond bar square triangle pin pie
          markerType: 'square',
          // 绘制的marker的填充色
          markerFill: '#1bbc9b',
          // 绘制的线的颜色
          markerLineColor: '#000',
          // 绘制的线的宽度
          markerLineWidth: 1,
          // 绘制的marker大小
          markerWidth: 10,
          markerHeight: 10
        },

        labelOptions: {
          textSymbol: {
            // 文本呈现的样式，默认是: monospace, 当你设置 textFont时会覆盖这个属性
            textFaceName: 'monospace',
            // 文本填充色（字体颜色）
            textFill: '#fff',
            // 行距
            textLineSpacing: 1,
            // 对齐方式
            textHorizontalAlignment: 'right',
            // 文本标签与marker的距离，也就是与打点的位置的距离
            textDx: 20,
            // 标签的线的颜色
            markerLineColor: '#b4b3b3',
            // 标签的填充色
            markerFill: '#000'
          },
          boxStyle: {
            // 标签的padding， 第一个值是左右的padding，第二个是上下的padding
            padding: [6, 5],
            symbol: {
              // 绘制的marker类型，也就是简单形状，支持：ellipse cross x diamond bar square triangle pin pie
              markerType: 'square',
              markerFill: '#000',
              markerFillOpacity: 0.9,
              markerLineColor: '#b4b3b3'
            }
          }
        },
        // 清楚按钮的symbol
        clearButtonSymbol: [{
          markerType: 'square',
          markerFill: '#000',
          markerLineColor: '#b4b3b3',
          markerLineWidth: 2,
          markerWidth: 15,
          markerHeight: 15,
          markerDx: 20
        }, {
          markerType: 'x',
          markerWidth: 10,
          markerHeight: 10,
          markerLineColor: '#fff',
          markerDx: 20
        }],
        language: 'zh-CN',
        once: true
      }).addTo(this.mapEngine)
        .on('drawend', p => {
          console.log('地图坐标:' + p.coordinate)
          console.log('界面坐标：' + p.containerPoint)
          console.log('测量距离：' + p.drawTool.getLastMeasure() + '米')
        })
    },

    /**
       * 绘制工具
       */
    addDrawTool (layer) {
      const drawTool = new maptalks.DrawTool({
        mode: 'Point'
      }).addTo(this.mapEngine)
        .disable()

      drawTool.on('drawend', function (param) {
        layer.addGeometry(param.geometry)
      })

      this.drawTool = drawTool
      return drawTool
    },

    /**
     *增加绘制工具栏
     */
    addDrawToolbar (layer) {
      const _t = this

      const items = [{code: 'Point', name: '点'},
        {code: 'LineString', name: '线'},
        {code: 'Polygon', name: '几何面'},
        {code: 'Circle', name: '圆'},
        {code: 'Ellipse', name: '椭圆'},
        {code: 'Rectangle', name: '矩形'},
        {code: 'FreeHandLineString', name: '自由绘制'},
        {code: 'FreeHandPolygon', name: '任意几何面'}]
        .map(function (value) {
          return {
            item: value.name,
            click: function () {
              _t.drawTool.setMode(value.code).enable()
            }
          }
        })
      new maptalks.control.Toolbar({
        position: {
          top: 100,
          right: 50
        },
        items: [
          {
            item: '绘制工具',
            children: items
          },
          {
            item: '测面工具',
            click: function () {
              if (_t.areaTool.isEnabled()) {
                _t.areaTool.disable()
              } else {
                _t.areaTool.enable()
              }
            }
          },
          {
            item: '禁用',
            click: function () {
              _t.drawTool.disable()
            }
          },
          {
            item: '清除',
            click: function () {
              layer.clear()
            }
          }
        ]
      }).addTo(this.mapEngine)
    },

    /**
     * 测面工具
     */
    addAreaTool () {
      const areaTool = new maptalks.AreaTool({
        once: true,
        // 请看 symbol属性说明文档：https://github.com/maptalks/maptalks.js/wiki/Symbol-Reference
        symbol: {
          lineColor: '#1bbc9b',
          lineWidth: 2,
          polygonFill: '#fff',
          polygonOpacity: 0.3
        },
        vertexSymbol: {
          // 绘制的marker类型，也就是简单形状，支持：ellipse cross x diamond bar square triangle pin pie
          markerType: 'ellipse',
          // 绘制的marker的填充色
          markerFill: '#34495e',
          // 绘制的线的颜色
          markerLineColor: '#1bbc9b',
          // 绘制的线的宽度
          markerLineWidth: 3,
          // 绘制的marker大小
          markerWidth: 10,
          markerHeight: 10
        },
        // 文本标签属性
        labelOptions: {
          textSymbol: {
            // 文本呈现的样式，默认是: monospace, 当你设置 textFont时会覆盖这个属性
            textFaceName: 'monospace',
            // 文本填充色（字体颜色）
            textFill: '#fff',
            // 行距
            textLineSpacing: 1,
            // 对齐方式
            textHorizontalAlignment: 'right',
            // 文本标签与marker的距离，也就是与打点的位置的距离
            textDx: 15
          },
          boxStyle: {
            // 标签的padding， 第一个值是左右的padding，第二个是上下的padding
            padding: [6, 2],
            symbol: {
              markerType: 'square',
              markerFill: '#000',
              markerFillOpacity: 0.9,
              markerLineColor: '#b4b3b3'
            }
          }
        },
        clearButtonSymbol: [{
          markerType: 'square',
          markerFill: '#000',
          markerLineColor: '#b4b3b3',
          markerLineWidth: 2,
          markerWidth: 15,
          markerHeight: 15,
          markerDx: 22
        }, {
          markerType: 'x',
          markerWidth: 10,
          markerHeight: 10,
          markerLineColor: '#fff',
          markerDx: 22
        }],
        language: 'zh-CN'
      }).addTo(this.mapEngine)
      // 默认关闭
      areaTool.disable()
      this.areaTool = areaTool
      return areaTool
    },

    /**
     * 地图动画
     */
    mapAnimate () {
      const _t = this
      _t.mapEngine.animateTo({
        center: [118.13245430046891, 24.495713873147764],
        zoom: 13,
        pitch: 0,
        bearing: 20
      }, {
        duration: 5000
      })
      setTimeout(function () {
        _t.mapEngine.animateTo({
          center: [118.087828, 24.462059],
          zoom: 14,
          pitch: 65,
          bearing: 360
        }, {
          duration: 7000
        })
      }, 5000)
      setTimeout(function () {
        _t.checkList = []
        _t.checkList.push('学校')
        _t.handleCheckChange(_t.checkList)
      }, 9000)
    },

    /**
     * 增加动画播放按钮
     */
    addAnimateToolbar () {
      const _t = this
      new maptalks.control.Toolbar({
        position: {
          top: 150,
          right: 50
        },
        items: [
          {
            item: '播放',
            click: function () {
              _t.mapAnimate()
            }
          }
        ]
      }).addTo(this.mapEngine)
    }
  }
}
</script>

<style scoped lang="scss">
    html, body {
        margin: 0px;
        height: 100%;
        width: 100%;
    }

    .container {
        width: 100%;
        height: 100%;
        position: absolute
    }

    .map-toolbar {
        position: relative;
        z-index: 1000;
        width: 500px;
        height: 50px;
        float: left;
        top: 10px;
        left: 100px;
        background-color: #fff;
        border-radius: 5px;
        padding: 10px;

    }

    .map-container {
        width: 100%;
        height: 100%
    }
</style>
